package cn.cyh.queue_service.mq.producer;

import cn.cyh.queue_service.config.RabbitMQConfig;
import cn.cyh.queue_service.mq.event.*;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageProperties;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.stereotype.Service;

import java.io.Serializable;
import java.util.Date;
import java.util.UUID;

/**
 * RabbitMQ事件消息生产者实现类
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class RabbitEventProducer implements EventProducer {

    private final RabbitTemplate rabbitTemplate;
    private final ObjectMapper objectMapper;
    
    @Override
    public void sendTakeNumberEvent(TakeNumberEvent event) {
        String exchange = RabbitMQConfig.EXCHANGE_TOPIC;
        String routingKey = RabbitMQConfig.ROUTING_TAKE_NUMBER;
        sendMessage(exchange, routingKey, event);
    }
    
    @Override
    public void sendStatusChangeEvent(StatusChangeEvent event) {
        String exchange = RabbitMQConfig.EXCHANGE_TOPIC;
        String routingKey = "status.change";
        sendMessage(exchange, routingKey, event);
        log.info("发送状态变更事件消息: {} {} -> {}", event.getTicketNumber(), event.getOldStatus(), event.getNewStatus());
    }
    
    @Override
    public void sendNewCallEvent(NewCallEvent event) {
        String exchange = RabbitMQConfig.EXCHANGE_TOPIC;
        String routingKey = "notification.call";
        sendMessage(exchange, routingKey, event);
        log.info("发送叫号事件消息: {} -> 窗口{}", event.getTicketNumber(), event.getWindowNumber());
    }
    
    @Override
    public void sendVerifyEvent(VerifyEvent event) {
        String exchange = RabbitMQConfig.EXCHANGE_TOPIC;
        String routingKey = "call.event.verify";
        sendMessage(exchange, routingKey, event);
        log.info("发送验证事件消息: {} {}", event.getTicketNumber(), event.isVerified() ? "验证通过" : "验证失败");
    }
    
    @Override
    public void sendCompleteServiceEvent(CompleteServiceEvent event) {
        String exchange = RabbitMQConfig.EXCHANGE_TOPIC;
        String routingKey = "call.event.complete";
        sendMessage(exchange, routingKey, event);
        log.info("发送服务完成事件消息: {} 状态: {}", event.getTicketNumber(), event.getStatus());
    }
    
    @Override
    public void sendWindowStatusEvent(WindowStatusEvent event) {
        String exchange = RabbitMQConfig.EXCHANGE_TOPIC;
        String routingKey = "window.event.status." + event.getStatus().toLowerCase();
        sendMessage(exchange, routingKey, event);
        log.info("发送窗口状态事件消息: 窗口{} 状态: {}", event.getWindowNumber(), event.getStatus());
    }
    
    @Override
    public void sendStatsUpdateEvent(StatsUpdateEvent event) {
        String exchange = RabbitMQConfig.EXCHANGE_TOPIC;
        String routingKey = "statistics.update";
        sendMessage(exchange, routingKey, event);
        log.info("发送统计数据更新事件消息: 类型: {}", event.getStatsType());
    }
    
    @Override
    public void sendLogMessage(String level, String message) {
        String exchange = RabbitMQConfig.EXCHANGE_TOPIC;
        String routingKey = "log.message";
        
        // 构造日志消息
        LogMessage logMessage = new LogMessage();
        logMessage.setLevel(level);
        logMessage.setMessage(message);
        logMessage.setTimestamp(System.currentTimeMillis());
        
        sendMessage(exchange, routingKey, logMessage);
    }
    
    /**
     * 发送消息到RabbitMQ
     *
     * @param exchange 交换机
     * @param routingKey 路由键
     * @param event 事件消息对象
     */
    private void sendMessage(String exchange, String routingKey, Object event) {
        try {
            String message = objectMapper.writeValueAsString(event);
            
            // 设置消息属性
            MessageProperties properties = new MessageProperties();
            properties.setContentType(MessageProperties.CONTENT_TYPE_JSON);
            properties.setTimestamp(new Date());
            properties.setMessageId(UUID.randomUUID().toString());
            
            Message rabbitMessage = new Message(message.getBytes(), properties);
            
            // 发送消息
            rabbitTemplate.convertAndSend(exchange, routingKey, rabbitMessage);
        } catch (Exception e) {
            log.error("发送消息失败", e);
            throw new RuntimeException("发送消息失败", e);
        }
    }
    
    /**
     * 日志消息类
     */
    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    private static class LogMessage implements Serializable {
        private static final long serialVersionUID = 1L;
        private String level;
        private String message;
        private Long timestamp;
    }
} 